package events

// DomainEventProducer 领域事件生产者接口 所有聚合根实现这个接口 也就是实现了这个接口的事件生产者才能调用接口获取事件
// 一个是获取聚合根里保存的事件
// 一个是清空聚合根里保存的事件
// 聚合根实现了这两个方法后，事件发布者就可以通过这个接口获取事件进行发布
type DomainEventProducer interface {
	GetDomainEvents() []DomainEvent
	ClearDomainEvents()
}

// DomainEventPublisher 领域事件发布者
type DomainEventPublisher struct {
	eventBus EventBus
}

func NewDomainEventPublisher(eventBus EventBus) *DomainEventPublisher {
	return &DomainEventPublisher{
		eventBus: eventBus,
	}
}

// 订阅事件
func (b *DomainEventPublisher) Subscribe(eventType string, handler EventHandler) {
	b.eventBus.Subscribe(eventType, handler)
}

// 取消订阅
func (b *DomainEventPublisher) Unsubscribe(eventType string, handler EventHandler) {
	b.eventBus.Unsubscribe(eventType, handler)
}

// 通用的发布方法
func (p *DomainEventPublisher) PublishEvents(producers ...DomainEventProducer) {
	for _, producer := range producers {
		for _, event := range producer.GetDomainEvents() {
			p.eventBus.Publish(event)
		}
		// 这里只是简单的一次性把全部的消息都拿出来进行发送，然后清空消息，实际业务还可以对消息做筛选后再做其它的处理
		producer.ClearDomainEvents()
	}
}

// 支持单个聚合根
func (p *DomainEventPublisher) Publish(producer DomainEventProducer) {
	p.PublishEvents(producer)
}
